<?php

namespace maotool\orm\mapper;

use maotool\core\Container;
use maotool\core\contracts\MapperBaseResultType;
use maotool\orm\mapper\MapperLoader;
use maotool\orm\mapper\PageHelper;
use maotool\orm\mapper\PageInfo;
use maotool\orm\mapper\PageParam;
use maotool\orm\mapper\MapperTagProcessor;
use maotool\orm\mapper\MapperUtil;
use maotool\core\facade\Config;
use maotool\exception\RuntimeException;
use maotool\log\Console;
use maotool\orm\MapperObjectHandle;
use PDO;

class MapperObject
{
    private static $path = "";

    public function __call($method, $arguments)
    {
        $config = Config::get("database.connections.mysql");
        Console::debug(["mysql:host=" . $config["hostname"] . ";port=" . $config["hostport"] . ";dbname=" . $config["database"] . ";charset=" . $config["charset"], $config["username"], $config["password"]]);
        $pdoParam = [
            PDO::ATTR_CASE              => PDO::CASE_NATURAL,
            PDO::ATTR_ERRMODE           => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_ORACLE_NULLS      => PDO::NULL_NATURAL,
            PDO::ATTR_STRINGIFY_FETCHES => false,
            PDO::ATTR_EMULATE_PREPARES  => false,
            PDO::ATTR_PERSISTENT  => true,
        ];
        $log_time_start = microtime(true);
        $pdo = new PDO("mysql:host=" . $config["hostname"] . ";port=" . $config["hostport"] . ";dbname=" . $config["database"] . ";charset=" . $config["charset"],
            $config["username"], $config["password"], $pdoParam);
        $pdo->query("SET NAMES {$config["charset"]}");
        $mapper = MapperLoader::parse($method, base64_decode(self::$path), $arguments);
        $mapperObjectHandles = Container::getInterfaces(MapperObjectHandle::class);
        foreach ($mapperObjectHandles as $mapperObjectHandle) {
            $mapper = $mapperObjectHandle->beforeSubmit($mapper);
        }
        Console::debug($mapper);
        Console::debug('PDO连接用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
        $log_time_start = microtime(true);
        if ($mapper["type"] == "select") {
            if (in_array($mapper["resultType"], [MapperBaseResultType::OBJECT, MapperBaseResultType::ARRAY_])) {
                $sth = $pdo->prepare("select * from (" . $mapper["sql"] . ") rows_fast limit 1");
                for ($i = 0; $i < count($mapper['vars']); $i++) {
                    $sth->bindParam($i + 1, $mapper['vars'][$i]);
                }
                $sth->execute();
                if ($mapper["resultType"] === MapperBaseResultType::OBJECT) {
                    $data = $sth->fetch(PDO::FETCH_OBJ);
                    Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
                    return $data;
                } else {
                    $data = $sth->fetch(PDO::FETCH_ASSOC);
                    Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
                    return $data === false ? null : $data;
                }
            } else if ($mapper["resultType"] == MapperBaseResultType::COLUMN) {
                $sth = $pdo->prepare("select * from (" . $mapper["sql"] . ") mapper_list limit 1");
                for ($i = 0; $i < count($mapper['vars']); $i++) {
                    $sth->bindParam($i + 1, $mapper['vars'][$i]);
                }
                $sth->execute();
                $data = $sth->fetchColumn(0);
                Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
                return $data;
            } else if (in_array($mapper["resultType"], [MapperBaseResultType::LIST_, MapperBaseResultType::ARRAYS])) {
                $page = PageHelper::getLocalPage();
                if (isset($page)) {
                    // 统计总数
                    $sthTotal = $pdo->prepare("select count(*) as rows_count from (" . $mapper["sql"] . ") mapper_list");
                    for ($i = 0; $i < count($mapper['vars']); $i++) {
                        $sthTotal->bindParam($i + 1, $mapper['vars'][$i]);
                    }
                    $sthTotal->execute();
                    $page->setTotal($sthTotal->fetchColumn(0));
                    // 获取列表
                    if ($page->getTotal() > 0) {
                        $sth = $pdo->prepare("select * from (" . $mapper["sql"] . ") mapper_list LIMIT " . $page->getPageSize() . " OFFSET " . (($page->getPageNum() - 1) * $page->getPageSize()));
                        for ($i = 0; $i < count($mapper['vars']); $i++) {
                            $sth->bindParam($i + 1, $mapper['vars'][$i]);
                        }
                        $sth->execute();
                        if ($mapper["resultType"] == MapperBaseResultType::LIST_) {
                            $data = $sth->fetchAll(PDO::FETCH_OBJ);
                            Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
                            return $data;
                        } else {
                            $data = $sth->fetchAll(PDO::FETCH_ASSOC);
                            Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
                            return $data;
                        }
                    } else {
                        Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
                        return [];
                    }
                } else {
                    $sth = $pdo->prepare($mapper["sql"]);
                    for ($i = 0; $i < count($mapper['vars']); $i++) {
                        $sth->bindParam($i + 1, $mapper['vars'][$i]);
                    }
                    $sth->execute();
                    if ($mapper["resultType"] == MapperBaseResultType::LIST_) {
                        $data = $sth->fetchAll(PDO::FETCH_OBJ);
                        Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
                        return $data;
                    } else {
                        $data = $sth->fetchAll(PDO::FETCH_ASSOC);
                        Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
                        return $data;
                    }
                }
            } else {
                throw new RuntimeException("未知的mapper返回类型");
            }
        } else if ($mapper["type"] == "insert") {
            $sth = $pdo->prepare($mapper["sql"]);
            for ($i = 0; $i < count($mapper['vars']); $i++) {
                $sth->bindParam($i + 1, $mapper['vars'][$i]);
            }
            $sth->execute();
            $data = $sth->rowCount();
            Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
            return $data;
        } else if ($mapper["type"] == "update") {
            $sth = $pdo->prepare($mapper["sql"]);
            for ($i = 0; $i < count($mapper['vars']); $i++) {
                $sth->bindParam($i + 1, $mapper['vars'][$i]);
            }
            $sth->execute();
            $data = $sth->rowCount();
            Console::debug('PDO执行用时：' . number_format(microtime(true) - $log_time_start, 10) . ' 秒。');
            return $data;
        } else {
            throw new RuntimeException("未知的mapper类型");
        }
    }

}

return new MapperObject();